package com.scs.application.modules.upms.gendir;

import com.scs.application.ScpApplication;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
import com.scs.application.core.utils.FileUtils;
import com.scs.application.core.utils.FreeMarkers;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.upms.entity.GenTable;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;

import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 */
@Slf4j
public class GenUtils {

    private static XStream xStream = new XStream();

    static {
        xStream.alias("template", GenTemplate.class);

        /**
         * 设置安全防护，同时设置允许的类。否则会报warn：Security framework of XStream not initialized, XStream is probably vulnerable
         */
        XStream.setupDefaultSecurity(xStream);
        xStream.allowTypes(new Class[]{GenTemplate.class});
    }

    /**
     * 根据模板分类获取生成模板目录
     *
     * @param category 模板分类
     * @return 模板目录的绝对路径
     */
    public static String getTemplateDirectory(String category) {
//        Thread.currentThread().getContextClassLoader().getResource("/templates/gen/" +   category);

        String classPath = new File(ScpApplication.class.getClassLoader().getResource("").getPath()).getAbsolutePath();
        String templateDir = classPath;

        return templateDir + "/templates/gen/" + category;
    }

    /**
     * 生成代码
     *
     * @param genTable
     * @param isReplaceFile
     * @return
     */
    public static List<String> generateToFile(GenTable genTable, boolean isReplaceFile) throws IOException {

        String templateDirectory = GenUtils.getTemplateDirectory(genTable.getTplCategory());

        log.info("代码模板目录：{}", templateDirectory);

        File[] fileList = new File(templateDirectory).listFiles();


        List<String> messages = Lists.newArrayList();
        for (File file : fileList) {
            messages.add(generateFile(genTable, null, isReplaceFile, file));
        }


        List<GenTable> childTableList = genTable.getChildTableList();
        if (CollectionUtils.isEmpty(childTableList)) {
            return messages;
        }
        // 如果是子表的模板
        for (GenTable table : childTableList) {
            templateDirectory = GenUtils.getTemplateDirectory(table.getTplCategory());
            fileList = new File(templateDirectory).listFiles();
            for (File file : fileList) {
                messages.add(generateFile(table, genTable, isReplaceFile, file));
            }
        }
        return messages;
    }

    private static String generateFile(GenTable genTable, GenTable parentTable, boolean isReplaceFile, File file) throws IOException {
        String fileContent = FileUtils.readFileToString(file, "utf-8");
        String xmlContent = FreeMarkers.renderString(StringUtils.trimToEmpty(fileContent), getDataModel(genTable, parentTable));

        // 获取模板内容，将模板内容转换成实体
        GenTemplate tpl = (GenTemplate) xStream.fromXML(xmlContent);


        tpl.setFileDir(StringUtils.replaceEach(tpl.getFileDir(),
                new String[]{"//", "/", "."}, new String[]{File.separator, File.separator, File.separator}));

        String filePath = tpl.getFileDir() + File.separator + tpl.getFileName();

        //如果选择替换文件，则删除原文件
        if (isReplaceFile) {
            FileUtils.deleteFile(filePath);
        }
        //创建并写入文件
        if (FileUtils.createFile(filePath)) {
            FileUtils.writeToFile(filePath, tpl.getContent(), true);
            return "生成成功：" + filePath;
        } else {
            return "文件已存在：" + filePath;
        }
    }


    private static Map<String, Object> getDataModel(GenTable genTable, GenTable parentTable) {
        HashMap<String, Object> map = Maps.newHashMap();
        map.put("table", genTable);

        map.put("className", StringUtils.defaultString(genTable.getClassName()));
        map.put("uncamelClassName", StringUtils.defaultString(StringUtils.uncamelCase(genTable.getClassName())));
        map.put("tableName", StringUtils.defaultString(genTable.getTableName()));
        map.put("packageName", StringUtils.defaultString(genTable.getPackageName()));
        map.put("moduleName", StringUtils.defaultString(genTable.getModuleName()));
        map.put("subModuleName", StringUtils.defaultString(genTable.getSubModuleName()));
        map.put("functionAuthor", StringUtils.defaultString(genTable.getFunctionAuthor()));
        map.put("functionName", StringUtils.defaultString(genTable.getFunctionName()));
        map.put("parentTableFkName", StringUtils.camelCase(StringUtils.defaultString(genTable.getParentTableFkName())));
        map.put("childTableList", genTable.getChildTableList() == null ? Lists.newArrayList() : genTable.getChildTableList());

        if (parentTable != null) {
            map.put("parentClassName", parentTable.getClassName());
        }

        String genBaseDir;
        if (StringUtils.isBlank(genTable.getGenBaseDir())) {
            // 默认桌面路径
            genBaseDir = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath();
        } else {
            genBaseDir = genTable.getGenBaseDir();
        }
        genTable.setGenBaseDir(genBaseDir);
        map.put("genBaseDir", genTable.getGenBaseDir());


        // 组件列表，用于子表
        List<String> componentNameList = genTable.getColumns().stream().map(tmp -> {
            switch (tmp.getShowType()) {
                case "warehouseSelect":
                    return "WarehouseTableSelect";
                case "warehouseAreaSelect":
                    return "WarehouseAreaTableSelect";
                case "warehouseLocationSelect":
                    return "WarehouseLocationTableSelect";
                case "materialSelect":
                    return "MaterialTableSelect";
                case "packUnitSelect":
                    return "PackUnitTableSelect";
                case "richTextEditor":
                    return "RichTextEditor";
                case "userSelect":
                    return "UserTableSelect";
                case "officeSelect":
                    return "OfficeTreeSelect";
                default:
                    return null;
            }
        }).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
        map.put("componentNameList", componentNameList);

        List<String> importComponentList = componentNameList.stream().map(tmp -> {
            switch (tmp) {
                case "WarehouseTableSelect":
                    return "import WarehouseTableSelect from '@/components/base/WarehouseTableSelect'";
                case "WarehouseAreaTableSelect":
                    return "import WarehouseAreaTableSelect from '@/components/base/WarehouseAreaTableSelect'";
                case "WarehouseLocationTableSelect":
                    return "import WarehouseLocationTableSelect from '@/components/base/WarehouseLocationTableSelect'";
                case "MaterialTableSelect":
                    return "import MaterialTableSelect from '@/components/base/MaterialTableSelect'";
                case "PackUnitTableSelect":
                    return "import PackUnitTableSelect from '@/components/base/PackUnitTableSelect'";
                case "RichTextEditor":
                    return "import RichTextEditor from '@/components/common/RichTextEditor'";
                case "UserTableSelect":
                    return "import UserTableSelect from '@/components/sys/UserTableSelect'";
                case "OfficeTreeSelect":
                    return "import OfficeTreeSelect from '@/components/sys/OfficeTreeSelect'";
                default:
                    return null;
            }

        }).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
        map.put("importComponentList", importComponentList);

//        map.put("vc", new ValidatorsCoverterMethod());

        return map;
    }



}
